import {
  ArgumentMetadata,
  BadRequestException,
  DefaultValuePipe,
  HttpException,
  HttpStatus,
  Injectable,
  PipeTransform,
} from '@nestjs/common';
import { plainToClass } from 'class-transformer';
import { validate } from 'class-validator';

/* 全局 dto 验证管道 */

@Injectable()
export class ValidationPipe implements PipeTransform {
  /**
   * 验证请求 dto 参数
   * @param value 当前处理的参数
   * @param metadata 属性的元类型
   * @returns 验证后的值
   */
  async transform(value: any, metadata: ArgumentMetadata) {
    if (!metadata.metatype || !this.toValidate(metadata.metatype)) {
      return value;
    }

    // plainToClass 将普通的 js 对象转换为特定类的实例
    const object = plainToClass(metadata.metatype, value);

    // 验证该对象返回出错的数组
    const errors = await validate(object);
    if (errors.length > 0) {
      // 将错误信息数组中的第一个内容返回给异常过滤器
      const errorMsg = errors.shift().constraints;
      throw new BadRequestException(errorMsg);
    }
    return value;
  }

  // 验证属性值的元类型是否是 String、Boolean、Number、Array、Object 中的一种
  private toValidate(metatype: any): boolean {
    const types: Function[] = [String, Boolean, Number, Array, Object];
    return !types.includes(metatype);
  }
}
